# HUB 插件 - 文件下载模块
# 实现从HUB模型快递站下载模型并导入到SketchUp功能

require 'sketchup.rb'
require 'net/http'
require 'uri'
require 'json'
require 'tempfile'
require 'fileutils'
require_relative 'config'
require_relative 'ui'

module HUB
  # 跟踪最后一次下载的时间
  @last_download_time = nil
  @cooldown_seconds = 10  # 默认值，会被远程配置覆盖
  @download_timeout = 180  # 默认连接超时值，会被远程配置覆盖
  @remote_config_loaded = false
  
  # 从远程加载下载配置
  def self.load_download_config
    begin
      remote_config_url = "http://api.cdsjcc.cn/hub/ss1.txt"
      log("使用远程配置")
      
      uri = URI(remote_config_url)
      http_options = { 
        use_ssl: uri.scheme == 'https',
        open_timeout: 5,  # 配置加载使用短超时
        read_timeout: 10
      }
      
      config_text = ""
      
      Net::HTTP.start(uri.hostname, uri.port, http_options) do |http|
        request = Net::HTTP::Get.new(uri)
        request['User-Agent'] = 'Mozilla/5.0 SketchUp HUB Plugin'
        
        # 发送请求获取配置
        http.request(request) do |response|
          if response.code == '200'
            config_text = response.body
          else
            log("获取远程配置失败，状态码: #{response.code}", LOG_ERROR)
            return false
          end
        end
      end
      
      # 解析配置文本
      log("成功获取配置数据，长度: #{config_text.length} 字节")
      
      # 解析下载连接超时
      timeout_match = config_text.match(/\[xzcs\]="?(\d+)"?/)
      if timeout_match && timeout_match[1]
        new_timeout = timeout_match[1].to_i
        if new_timeout > 0
          @download_timeout = new_timeout
          log("远程配置：下载连接超时 = #{@download_timeout} 秒")
        end
      end
      
      # 解析下载间隔时间
      cooldown_match = config_text.match(/\[xzjg\]="?(\d+)"?/)
      if cooldown_match && cooldown_match[1]
        new_cooldown = cooldown_match[1].to_i
        if new_cooldown > 0
          @cooldown_seconds = new_cooldown
          log("远程配置：下载间隔时间 = #{@cooldown_seconds} 秒")
        end
      end
      
      @remote_config_loaded = true
      return true
      
    rescue => e
      log("加载远程下载配置出错: #{e.message}", LOG_ERROR)
      return false
    end
  end
  
  # 下载模型主函数
  def self.download_model_impl
    begin
      log("开始下载模型流程")
      
      # 首次运行时加载远程配置
      load_download_config() unless @remote_config_loaded
      
      # 检查冷却时间
      if @last_download_time && (Time.now - @last_download_time) < @cooldown_seconds
        remaining = @cooldown_seconds - (Time.now - @last_download_time).to_i
        message = "请稍等 #{remaining} 秒后再尝试下载"
        log(message, LOG_INFO)
        UIHelper.show_status_text(message)
        UIHelper.show_error("下载功能正在冷却中，请稍等 #{remaining} 秒")
        return
      end
      
      # 确保临时目录存在，与上传功能共用同一目录
      temp_dir = ensure_temp_dir
      
      # 获取用户输入的提取码
      result = get_extraction_code_from_user()
      
      # 检查返回结果
      if result.nil?
        log("用户取消了操作", LOG_INFO)
        return
      end
      
      extraction_code = result[:extraction_code]
      model_name = result[:model_name]
      
      # 显示状态信息
      UIHelper.show_status_text("正在准备下载模型，提取码: #{extraction_code}...")
      
      # 直接使用自动下载功能，后台静默完成
      log("使用自动下载功能")
      
      # 设置最后下载时间
      @last_download_time = Time.now
      
      direct_download_model(extraction_code, model_name, temp_dir)
      
    rescue => e
      UIHelper.show_error("下载过程中发生错误: #{e.message}")
      log("下载过程中发生错误: #{e.message}\n#{e.backtrace.join("\n")}", LOG_ERROR)
      UIHelper.show_status_text("")
    end
  end
  
  # 传统浏览器下载方法（原有方法逻辑）
  def self.traditional_download_model(extraction_code, model_name, hub_url)
    # 使用浏览器打开下载页面
    log("打开浏览器下载页面: #{hub_url}")
    UIHelper.show_status_text("正在打开浏览器下载页面...")
    
    # 打开浏览器
    UI.openURL(hub_url)
    
    # 提示用户
    message = "已在浏览器中打开HUB平台页面，请按以下步骤操作:\n\n"
    message += "1. 在输入框中输入5位取件码: #{extraction_code}\n"
    message += "2. 点击确认按钮\n"
    message += "3. 系统会显示取件记录列表，第一条是最新的记录\n"
    message += "4. 点击该记录右侧的下载图标(↓)保存模型文件\n\n"
    message += "下载完成后，是否需要导入模型到SketchUp？"
    
    if UIHelper.show_confirm(message)
      # 用户确认后导入本地文件
      UIHelper.show_status_text("请在下载完成后点击确定...")
      import_from_local()
    else
      UIHelper.show_message("您可以稍后通过【文件】->【导入】->【导入本地模型】将下载的模型导入到SketchUp。")
    end
    
    log("已打开浏览器下载页面，提取码: #{extraction_code}")
    UIHelper.show_status_text("请在浏览器中完成下载")
  end
  
  # 自动下载方法（全后台实现）
  def self.direct_download_model(extraction_code, model_name, temp_dir)
    begin
      log("开始后台自动下载模型，提取码: #{extraction_code}")
      UIHelper.show_status_text("正在准备下载...")
      
      # 标准化并确保路径有效
      download_dir = File.expand_path(temp_dir)
      log("下载目标目录: #{download_dir}")
      
      # 第一步：创建访问记录（但不打开浏览器）
      visit_url = "http://#{API_HOST}:#{API_PORT}/#/?code=#{extraction_code}"
      log("创建访问记录")
      
      # 使用Net::HTTP发送请求
      begin
        uri = URI(visit_url)
        http_options = { 
          use_ssl: uri.scheme == 'https',
          open_timeout: 10,
          read_timeout: 20
        }
        
        Net::HTTP.start(uri.hostname, uri.port, http_options) do |http|
          request = Net::HTTP::Get.new(uri)
          request['User-Agent'] = 'Mozilla/5.0 SketchUp HUB Plugin'
          
          # 发送请求记录访问
          http.request(request)
        end
        
        log("创建访问记录")
      rescue => e
        log("创建访问记录时出错: #{e.message}", LOG_WARN)
        # 继续执行，即使记录创建失败
      end
      
      # 等待一小段时间
      sleep(0.5)
      
      # 第二步：调用API下载文件
      download_api = "http://#{API_HOST}:#{API_PORT}/share/select/?code=#{extraction_code}"
      log("调用下载API")
      
      # 设置文件名
      target_filename = "sketchup_model_#{extraction_code}.skp"
      target_path = File.join(download_dir, target_filename)
      log("目标文件路径: #{target_path}")
      
      # 创建下载进度对话框
      progress_dialog = create_progress_dialog(target_filename)
      
      # 下载文件到临时目录
      begin
        uri = URI(download_api)
        http_options = { 
          use_ssl: uri.scheme == 'https',
          open_timeout: @download_timeout,  # 使用远程配置的超时时间
          read_timeout: @download_timeout   # 使用远程配置的超时时间
        }
        
        log("使用下载连接超时设置: #{@download_timeout}秒")
        
        # 开始下载
        progress_dialog.execute_script("updateStatus('正在下载文件...');")
        progress_dialog.execute_script("updateProgress(10);")
        
        Net::HTTP.start(uri.hostname, uri.port, http_options) do |http|
          request = Net::HTTP::Get.new(uri)
          request['User-Agent'] = 'Mozilla/5.0 SketchUp HUB Plugin'
          
          # 发送请求并获取响应
          http.request(request) do |response|
            
            # 检查响应状态
            if response.code != '200'
              error_message = "下载失败，服务器返回: #{response.code}"
              log(error_message, LOG_ERROR)
              UIHelper.show_error(error_message)
              progress_dialog.close
              return false
            end
            
            # 获取文件大小（如果有）
            content_length = response['Content-Length'].to_i
            bytes_downloaded = 0
            
            # 打开文件准备写入
            File.open(target_path, 'wb') do |file|
              response.read_body do |chunk|
                # 写入数据块
                file.write(chunk)
                
                # 更新进度
                bytes_downloaded += chunk.size
                if content_length > 0
                  progress = (bytes_downloaded.to_f / content_length * 80).to_i + 10
                  progress = [progress, 90].min  # 最大90%，留10%给文件处理
                  progress_dialog.execute_script("updateProgress(#{progress});")
                  progress_dialog.execute_script("updateFileInfo('已下载: #{(bytes_downloaded.to_f / 1024 / 1024).round(2)} MB / #{(content_length.to_f / 1024 / 1024).round(2)} MB');")
                else
                  # 如果无法获取总大小，显示已下载的大小
                  progress_dialog.execute_script("updateFileInfo('已下载: #{(bytes_downloaded.to_f / 1024 / 1024).round(2)} MB');")
                  # 模拟进度增长
                  progress_dialog.execute_script("updateProgress(Math.min(50 + #{bytes_downloaded / 10000}, 90));")
                end
              end
            end
          end
        end
        
        # 检查文件是否已下载
        if File.exist?(target_path) && File.size(target_path) > 0
          log("文件已成功下载到: #{target_path}")
          progress_dialog.execute_script("updateStatus('下载完成！准备导入...');")
          progress_dialog.execute_script("updateProgress(100);")
          progress_dialog.execute_script("downloadCompleted();")
          
          # 关闭进度对话框并自动导入
          sleep(0.5)  # 给用户时间短暂查看完成状态
          progress_dialog.close
          
          # 直接导入模型，不再询问
          log("自动导入下载的模型文件")
          import_model_from_path(target_path)
          
          return true
        else
          error_message = "下载似乎完成，但无法找到下载的文件或文件为空"
          log(error_message, LOG_ERROR)
          UIHelper.show_error(error_message)
          progress_dialog.close
          return false
        end
        
      rescue => e
        error_message = "下载文件时出错: #{e.message}"
        log(error_message, LOG_ERROR)
        log(e.backtrace.join("\n"), LOG_ERROR)
        UIHelper.show_error(error_message)
        progress_dialog.close if progress_dialog
        return false
      end
      
    rescue => e
      error_message = "直接下载过程中发生错误: #{e.message}"
      log(error_message, LOG_ERROR)
      log(e.backtrace.join("\n"), LOG_ERROR)
      UIHelper.show_error(error_message)
      
      UIHelper.show_status_text("")
      return false
    end
  end
  
  # 创建下载进度对话框
  def self.create_progress_dialog(filename)
    dialog = UI::HtmlDialog.new({
      dialog_title: "HUB文件下载",
      preferences_key: "HUB_DirectDownloader",
      scrollable: false,
      resizable: false,
      width: 550,
      height: 250,
      left: 100,
      top: 100,
      style: UI::HtmlDialog::STYLE_DIALOG
    })
    
    # HTML内容
    html = <<~HTML
      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="UTF-8">
        <title>HUB文件下载</title>
        <style>
          body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
          }
          .container {
            background-color: white;
            border-radius: 5px;
            padding: 15px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
          }
          h3 {
            margin-top: 0;
            color: #333;
          }
          .status {
            margin: 15px 0;
            padding: 10px;
            background-color: #f0f7ff;
            border-left: 4px solid #0066cc;
            color: #333;
          }
          .progress-container {
            width: 100%;
            height: 20px;
            background-color: #eee;
            border-radius: 10px;
            margin: 15px 0;
          }
          .progress-bar {
            height: 100%;
            background-color: #4CAF50;
            border-radius: 10px;
            width: 0%;
            transition: width 0.3s;
          }
          .file-info {
            margin-top: 10px;
            font-size: 0.9em;
            color: #666;
          }
        </style>
      </head>
      <body>
        <div class="container">
          <h3>HUB文件下载</h3>
          <div class="status" id="status">正在准备下载...</div>
          <div class="progress-container">
            <div class="progress-bar" id="progress-bar"></div>
          </div>
          <div class="file-info" id="file-info">准备下载文件: #{filename}</div>
        </div>

        <script>
          // 更新状态
          function updateStatus(message) {
            document.getElementById('status').innerText = message;
          }
          
          // 更新进度条
          function updateProgress(percent) {
            document.getElementById('progress-bar').style.width = percent + '%';
          }
          
          // 更新文件信息
          function updateFileInfo(info) {
            document.getElementById('file-info').innerText = info;
          }
          
          // 下载完成
          function downloadCompleted() {
            updateStatus('下载已完成！准备导入...');
            updateProgress(100);
          }
        </script>
      </body>
      </html>
    HTML
    
    # 设置HTML内容
    dialog.set_html(html)
    
    # 显示对话框
    dialog.show
    
    return dialog
  end
  
  # 获取提取码
  def self.get_extraction_code_from_user
    # 从剪贴板获取提取码
    clipboard_content = get_clipboard_content().to_s.strip
    log("从剪贴板获取内容: #{clipboard_content}", LOG_DEBUG)
    
    # 尝试解析提取码
    parsed_result = parse_extraction_code(clipboard_content)
    
    # 如果能解析，直接使用
    if parsed_result && parsed_result[:extraction_code]
      log("成功从剪贴板解析提取码: #{parsed_result[:extraction_code]}")
      
      # 询问用户是否使用解析出的提取码
      message = "已检测到提取码: #{parsed_result[:extraction_code]}\n"
      message += "模型名称: #{parsed_result[:model_name]}\n\n"
      message += "是否使用此提取码下载模型？"
      
      if UIHelper.show_confirm(message)
        return parsed_result
      end
    end
    
    # 如果不能解析或用户选择不使用，显示输入框
    log("显示输入对话框让用户手动输入提取码")
    default_value = parsed_result ? parsed_result[:extraction_code] : ""
    input = UIHelper.show_input_dialog("下载模型", "请输入提取码:", default_value)
    
    if input.nil? || input.empty?
      log("用户取消或未输入提取码", LOG_INFO)
      return nil
    end
    
    # 再次解析输入，获取提取码
    input = input.strip
    result = parse_extraction_code(input)
    
    if result.nil?
      # 如果无法解析，假设用户直接输入了提取码
      log("假设用户直接输入了提取码: #{input}")
      return {
        extraction_code: input,
        model_name: "下载的模型"
      }
    end
    
    return result
  end
  
  # 解析提取码
  def self.parse_extraction_code(text)
    return nil if text.nil? || text.empty?
    
    # 匹配格式: 【模型名称】模型提取码:12345
    match = text.match(/【(.+?)】模型提取码:(\d+)/)
    if match
      model_name = match[1].strip
      code = match[2].strip
      
      log("成功解析提取码: #{code}, 模型名称: #{model_name}", LOG_DEBUG)
      return {
        extraction_code: code,
        model_name: model_name
      }
    end
    
    # 尝试更宽松的匹配
    # 匹配格式: 模型提取码:12345
    match = text.match(/模型提取码:(\d+)/)
    if match
      code = match[1].strip
      
      log("使用宽松模式解析提取码: #{code}", LOG_DEBUG)
      return {
        extraction_code: code,
        model_name: "未命名模型"
      }
    end
    
    # 尝试直接匹配5位数字提取码
    match = text.match(/\b(\d{5,6})\b/)
    if match
      code = match[1]
      
      log("直接匹配数字作为提取码: #{code}", LOG_DEBUG)
      return {
        extraction_code: code,
        model_name: "未命名模型"
      }
    end
    
    log("无法从文本解析提取码: #{text}", LOG_DEBUG)
    return nil
  end
  
  # 从剪贴板获取内容
  def self.get_clipboard_content
    content = ""
    
    begin
      # 不同平台的剪贴板读取方法
      if RUBY_PLATFORM =~ /mswin|mingw|windows/i
        # Windows平台
        begin
          # 尝试使用win32ole库隐藏命令窗口
          begin
            require 'win32ole'
            
            # 创建临时文件
            temp_file = File.join(Dir.tmpdir, "hub_clipboard_#{Time.now.to_i}.txt")
            
            # 创建WScript.Shell对象
            shell = WIN32OLE.new('WScript.Shell')
            
            # 使用Run方法运行命令，参数0表示隐藏窗口，参数1表示等待命令完成
            cmd = "powershell -command \"Get-Clipboard | Out-File -FilePath '#{temp_file}' -Encoding utf8\""
            shell.Run(cmd, 0, 1)
            
            log("使用WIN32OLE读取剪贴板内容", LOG_DEBUG)
            
            # 读取临时文件
            if File.exist?(temp_file)
              content = File.read(temp_file, encoding: 'UTF-8').strip
              File.delete(temp_file) rescue nil
            end
          rescue LoadError
            # 如果win32ole库不可用，使用其他方法
            log("WIN32OLE库不可用，使用备选方法读取剪贴板", LOG_DEBUG)
            
            # 使用IO.popen尝试隐藏窗口
            temp_file = File.join(Dir.tmpdir, "hub_clipboard_#{Time.now.to_i}.txt")
            IO.popen("powershell -command \"Get-Clipboard | Out-File -FilePath '#{temp_file}' -Encoding utf8\"", "r") { |io| io.read }
            
            if File.exist?(temp_file)
              content = File.read(temp_file, encoding: 'UTF-8').strip
              File.delete(temp_file) rescue nil
            end
          end
        rescue => e
          log("从Windows剪贴板读取时出错: #{e.message}", LOG_ERROR)
        end
      elsif RUBY_PLATFORM =~ /darwin/i
        # macOS平台
        begin
          # 使用IO.popen替代system调用
          content = IO.popen("pbpaste", "r") { |io| io.read.to_s.strip }
          log("使用pbpaste读取剪贴板内容", LOG_DEBUG)
        rescue => e
          log("从macOS剪贴板读取时出错: #{e.message}", LOG_ERROR)
        end
      else
        log("不支持的平台，无法读取剪贴板", LOG_ERROR)
      end
    rescue => e
      log("获取剪贴板内容时出错: #{e.message}", LOG_ERROR)
    end
    
    return content
  end

  # 从本地导入模型文件
  def self.import_from_local
    begin
      # 首先检查Temp目录中是否有最新的模型文件
      temp_dir = ensure_temp_dir
      skp_files = Dir.glob(File.join(temp_dir, "*.skp")).sort_by { |f| File.mtime(f) }
      
      # 如果存在模型文件，询问用户是否导入最新的那个
      if !skp_files.empty?
        newest_file = skp_files.last
        file_name = File.basename(newest_file)
        file_time = File.mtime(newest_file).strftime("%Y-%m-%d %H:%M:%S")
        file_size = (File.size(newest_file) / 1024.0 / 1024.0).round(2)
        
        message = "在HUB\\Temp目录中发现模型文件:\n\n"
        message += "文件名: #{file_name}\n"
        message += "修改时间: #{file_time}\n"
        message += "文件大小: #{file_size} MB\n\n"
        message += "是否导入此文件？选择'否'可打开文件选择对话框。"
        
        if UIHelper.show_confirm(message)
          return import_model_from_path(newest_file)
        end
      end
      
      # 如果Temp目录没有文件或用户不想使用，打开文件选择对话框
      path = UI.openpanel("选择模型文件", temp_dir, "SketchUp Files|*.skp||")
      
      if path && !path.empty?
        return import_model_from_path(path)
      else
        log("用户取消了文件选择", LOG_INFO)
        UIHelper.show_status_text("")
        return false
      end
    rescue => e
      log("导入本地文件时出错: #{e.message}", LOG_ERROR)
      UIHelper.show_error("导入时出错: #{e.message}")
      return false
    end
  end

  # 从特定路径导入模型
  def self.import_model_from_path(path)
    begin
      if path && File.exist?(path)
        log("开始导入模型文件: #{path}")
        UIHelper.show_status_text("正在导入模型...")
        
        model = Sketchup.active_model
        
        # 开始导入操作
        model.start_operation('导入HUB模型', true)
        
        begin
          # 导入模型
          model.import(path)
          
          # 如果导入后有选中对象，缩放视图以适应
          if !model.selection.empty?
            view = model.active_view
            view.zoom(model.selection)
          end
          
          # 完成操作
          model.commit_operation
          
          log("✅ 模型成功导入：#{path}")
          UIHelper.show_status_text("模型导入成功")
          
          # 清空临时目录
          clear_temp_directory
          
          return true
        rescue => e
          model.abort_operation
          log("❌ 导入失败: #{e.message}", LOG_ERROR)
          UIHelper.show_error("导入失败: #{e.message}")
          return false
        end
      else
        log("⚠️ 文件不存在：#{path}", LOG_ERROR)
        UIHelper.show_error("模型文件不存在或无效")
        return false
      end
    rescue => e
      log("导入模型文件时出错: #{e.message}", LOG_ERROR)
      UIHelper.show_error("导入时出错: #{e.message}")
      return false
    end
  end
  
  # 清空临时目录
  def self.clear_temp_directory
    begin
      temp_dir = ensure_temp_dir
      log("正在清空临时目录: #{temp_dir}")
      
      # 查找所有文件
      files = Dir.glob(File.join(temp_dir, "*"))
      
      # 记录文件数量
      file_count = files.length
      log("找到 #{file_count} 个临时文件")
      
      # 删除所有文件
      files.each do |file|
        begin
          File.delete(file)
          log("已删除临时文件: #{file}", LOG_DEBUG)
        rescue => e
          log("删除临时文件失败: #{file}, 错误: #{e.message}", LOG_WARN)
        end
      end
      
      log("临时目录清理完成，共删除 #{file_count} 个文件")
    rescue => e
      log("清理临时目录时出错: #{e.message}", LOG_ERROR)
    end
  end

end # module HUB
